package gui;

import java.awt.Color;
import java.awt.Paint;
import java.util.Random;

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickMarkPosition;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.entity.ChartEntity;
import org.jfree.chart.entity.XYItemEntity;
import org.jfree.chart.event.RendererChangeEvent;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StackedXYBarRenderer;
import org.jfree.chart.renderer.xy.StandardXYBarPainter;
import org.jfree.data.time.Day;
import org.jfree.data.time.Hour;
import org.jfree.data.time.TimeTableXYDataset;
import org.jfree.data.xy.TableXYDataset;
import org.jfree.experimental.chart.swt.ChartComposite;

public class StackedChartSwt {
    private StackedRenderer renderer;
    private Color[] colors = new Color[]{
            new Color(230,240,255), 
            new Color(240,255,240), 
            new Color(255,255,255), 
            new Color(255,255,240), 
            new Color(255,240,240), 
            new Color(240,240,240)
    };

    public StackedChartSwt(){
        Display display = new Display();
        final Shell shell = new Shell(display);
        shell.setLayout(new FillLayout());

        JFreeChart chart = createStackedChart(createStackedDataset());
        ChartComposite chartComposite = new ChartComposite(shell, SWT.NONE, chart, false, false, false, false, false);
        chartComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
        chartComposite.setRangeZoomable(false);
        chartComposite.setMenu(null);
        chartComposite.addChartMouseListener(new ThisMouseListener());
        shell.setSize(800, 600);
        shell.open();

        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
              display.sleep();
            }
          }

          display.dispose();        
    }

    private JFreeChart createStackedChart(TableXYDataset tablexydataset) {
        DateAxis dateaxis = new DateAxis();
        dateaxis.setTickMarkPosition(DateTickMarkPosition.MIDDLE);
        NumberAxis numberaxis = new NumberAxis("Event counts");
        renderer = new StackedRenderer();
        XYPlot plot = new XYPlot(tablexydataset, dateaxis, numberaxis, renderer);
        plot.setBackgroundPaint(Color.white);
        plot.setDomainGridlinePaint(Color.lightGray);
        plot.setDomainGridlinesVisible(true);
        plot.setRangeGridlinesVisible(true);
        plot.setRangeGridlinePaint(Color.lightGray);

        JFreeChart chart = new JFreeChart(null, plot);
        chart.setBackgroundPaint(Color.white);
        chart.setBorderVisible(false);
        chart.setBorderPaint(null);

        return chart;
    }

    class StackedRenderer extends StackedXYBarRenderer{
        int selectedRow=-1, selectedCol=-1;
        public StackedRenderer(){
            setDrawBarOutline(true);
            setBarPainter(new StandardXYBarPainter());
            setShadowVisible(false);
            setSeriesPaint(0, Color.blue);
            setMargin(0.2);
        }

        public void select(int row, int col){
            selectedRow = row;
            selectedCol = col;
            notifyListeners(new RendererChangeEvent(this));
        }

        @Override
        public Paint getItemPaint(final int row, final int col){
            if(row == selectedRow && col == selectedCol)
                return Color.pink;
            return colors[row];
        }
    } 

    class ThisMouseListener implements ChartMouseListener{
        public void chartMouseMoved(ChartMouseEvent event){
        }

        public void chartMouseClicked(ChartMouseEvent event){
            ChartEntity entity = event.getEntity();
            if(entity != null && (entity instanceof XYItemEntity) ){
                XYItemEntity item = (XYItemEntity)entity;
                renderer.select(item.getSeriesIndex(), item.getItem());
                return;
            }

            // deselect
            renderer.select(-1,-1);
        }
    }

    private TableXYDataset createStackedDataset(){
        Random random = new Random(0);
        TimeTableXYDataset ds = new TimeTableXYDataset();
        Day day = new Day();
        for( int i = 0; i < 24; i++ ){
            Hour hour = new Hour( i, day );
            ds.add(hour, random.nextInt( 20 ), "A");
            ds.add(hour, random.nextInt( 20 ), "B");
            ds.add(hour, random.nextInt( 20 ), "C");
            ds.add(hour, random.nextInt( 20 ), "D");
            ds.add(hour, random.nextInt( 20 ), "E");
            ds.add(hour, random.nextInt( 20 ), "F");
        }

        return ds;
    }

    public static void main(String[] args){
        new StackedChartSwt();
    }
}

